{
  "cells": [
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pinecone-io/examples/blob/master/learn/analytics-and-ml/data-mining/sentiment-analysis/sentiment-analysis.ipynb) [![Open nbviewer](https://raw.githubusercontent.com/pinecone-io/examples/master/assets/nbviewer-shield.svg)](https://nbviewer.org/github/pinecone-io/examples/blob/master/learn/analytics-and-ml/data-mining/sentiment-analysis/sentiment-analysis.ipynb)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "zMAEGl3xfu6u"
      },
      "source": [
        "# Sentiment Analysis with Pinecone"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "jRtbBZg0NUiy"
      },
      "source": [
        "Sentiment analysis, often known as opinion mining, is a technique used in natural language processing (NLP) to determine the emotional undertone of a text. This is a common method used by organizations to identify and group opinions about their product, service, and ideas. In this notebook, we will apply this technique to the hotel industry and understand customer perception and potential areas that need improvement. To do this, we will:\n",
        "\n",
        "1.\tGenerate Sentiment labels and scores based on customer reviews.\n",
        "2.\tStore them in a Pinecone index as metadata (alongside respective text vectors).\n",
        "3.\tQuery Pinecone index on selected areas and understand customer opinions.\n",
        "\n",
        "Let's get started.\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "_iEQFegogJ7v"
      },
      "source": [
        "# Install Dependencies"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kj2fUHdd_wzL"
      },
      "outputs": [],
      "source": [
        "!pip install sentence_transformers pinecone-client==3.1.0 datasets seaborn matplotlib"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "0YXIqN6DgPsc"
      },
      "source": [
        "# Load and Prepare Dataset"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "hI5m1Qb0QaSF"
      },
      "source": [
        "We use a dataset containing ~90k hotel reviews provided by customers. This dataset can be loaded from the HuggingFace dataset hub as follows:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kj18hV5SgTQ6"
      },
      "outputs": [],
      "source": [
        "from datasets import load_dataset\n",
        "\n",
        "# load the dataset and convert to pandas dataframe\n",
        "df = load_dataset(\n",
        "    \"ashraq/hotel-reviews\",\n",
        "    split=\"train\"\n",
        ").to_pandas()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 206
        },
        "id": "0QY3pl3opq0k",
        "outputId": "7d0e1d9b-f9e7-4873-bcbe-303a6af93f76"
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-e185102e-db37-41cb-8524-1691d0ac13a3\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>review_date</th>\n",
              "      <th>hotel_name</th>\n",
              "      <th>review</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>8/3/2017</td>\n",
              "      <td>Park Plaza County Hall London</td>\n",
              "      <td>Extra bed was the worst breakfast queue was r...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>8/3/2017</td>\n",
              "      <td>Park Plaza County Hall London</td>\n",
              "      <td>Just the location and view</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>8/3/2017</td>\n",
              "      <td>Park Plaza County Hall London</td>\n",
              "      <td>Around the corner from the London eye and use...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>8/2/2017</td>\n",
              "      <td>Park Plaza County Hall London</td>\n",
              "      <td>I wish you had wheat free snacks</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>8/2/2017</td>\n",
              "      <td>Park Plaza County Hall London</td>\n",
              "      <td>You re always my hotel of choice You re staff...</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-e185102e-db37-41cb-8524-1691d0ac13a3')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-e185102e-db37-41cb-8524-1691d0ac13a3 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-e185102e-db37-41cb-8524-1691d0ac13a3');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "  review_date                     hotel_name  \\\n",
              "0    8/3/2017  Park Plaza County Hall London   \n",
              "1    8/3/2017  Park Plaza County Hall London   \n",
              "2    8/3/2017  Park Plaza County Hall London   \n",
              "3    8/2/2017  Park Plaza County Hall London   \n",
              "4    8/2/2017  Park Plaza County Hall London   \n",
              "\n",
              "                                              review  \n",
              "0   Extra bed was the worst breakfast queue was r...  \n",
              "1                         Just the location and view  \n",
              "2   Around the corner from the London eye and use...  \n",
              "3                   I wish you had wheat free snacks  \n",
              "4   You re always my hotel of choice You re staff...  "
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# keep only the first 800 characters from the reviews\n",
        "df[\"review\"] = df[\"review\"].str[:800]\n",
        "# glimpse the dataset\n",
        "df.head()"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "ciqKCl9gbN7s"
      },
      "source": [
        "# Initialize Sentiment Analysis Model"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "9pZkI5KIRYkE"
      },
      "source": [
        "We will use a RoBERTa model fine-tuned for sentiment analysis to analyze the hotel reviews. The model can be loaded from the HuggingFace model hub as follows:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kyu5qdDMooua"
      },
      "outputs": [],
      "source": [
        "import torch\n",
        "\n",
        "# set device to GPU if available\n",
        "device = 'cuda' if torch.cuda.is_available() else 'cpu'"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 177,
          "referenced_widgets": [
            "488b514507d5432da0d5b1c389f174cc",
            "18ddb860e57b4868b0566bca11023d84",
            "889545eaaf02423fbbf714204d10ef2d",
            "552a5a8d597f4a788e1340a4a4825083",
            "3efeb29f04d54d3ba54dbf6f25958e58",
            "4a7263794c8746d99107967bc1ac75f6",
            "53fd859fa08a41afb4a218cd21fe0457",
            "8ed41559628d4f9a9f106950f516d81a",
            "51553f4989a94ad18609519667299d79",
            "909c480f78184e3bafce6173f9028e71",
            "06bbddc010174cefb7c3d185bf41e5cf",
            "9b39688242ea451082925eebb0ad9017",
            "a114ca5722084fbb9375d15717cad0fd",
            "236b4fed6a3b46b0ae1b11adb6e7f54c",
            "87a785f0fc0a4859ad0cb0c78f151eed",
            "88cbc4d6dd43425eb8ef48b644eeb84b",
            "3b581541a17c477dac3c0045aaee8030",
            "a877435987354f3eb5b6b0c63975fb8c",
            "01484c7bd35341dda4c43070996de5c6",
            "6d6112f000254b939f5b7ebd7fdfd45e",
            "387afec80c604676917617cfebfa8694",
            "b4711eabf0484c90b617cfc9fdaedc42",
            "dad1bbe9c9af4a59ba8829fbfba58515",
            "f2613df9e4da42c797f69fd309fd85ad",
            "d149887c12184b86965d3bd2166ca650",
            "82564062262a4906ba680c0df2142842",
            "4f11728659db4c66b54552180f6b1ae0",
            "6781331dec7f4ea1953ec39565009937",
            "e939ed6a79cc415787a46f7d5ca7d440",
            "fced0aa3ab3549d99b33dde9a35982d8",
            "4f16a8b901c34716bdbd69cf98e5fdc3",
            "2729b36f31ad412d82aedfa92dd6fdd1",
            "15e91bb739f347c69521eda6e9f12da8",
            "95e200d3e7f74591ab589cfa1d1294c3",
            "4e49e483e6184fe9851bd8c4947327c7",
            "ad8f53afed0e438e9b004491ffaf2430",
            "8a2ea68e34b94bada266e77611ecc49e",
            "5c220d27469b43c09381187e9afa2239",
            "537d4049831c475dba11c31970d542be",
            "43bc8d2b731b414abe08d08a973592af",
            "bdac6045d06f40ebacf46979a050810a",
            "b90720eb6a5045df87dc914b01f80341",
            "ab8dc3e45c1c400d8ed3aa4fd7e4c165",
            "127fed0ac499432eb868a3dbb1e6e6eb",
            "895cfde25be34862a6e5bcb13b218e03",
            "b550791c7c814ac2bfc4d1f9a537b5d5",
            "d33f5fe230a24a98a96edcee9d768b77",
            "c251eabf1a974ae6a2cf6e7e05c32b94",
            "ede61f6c7a34492cb83b2f58bf9e47cf",
            "2c025804cf3d44eea098f5a84fb37de2",
            "dc7621caed4f48d9acbe87200531b48c",
            "c9a224880fcb47bdb4f4eb32bb09ff5a",
            "0e3afd7b8e844062bc6044f400827575",
            "541070fb0d104f2589a0f0f6cd2e5ec0",
            "ce32428c1eb841e799362ce01d90542b"
          ]
        },
        "id": "PiIVdrzah1ON",
        "outputId": "0fa7dc12-f297-400b-e3e1-0bf4223dcfcb"
      },
      "outputs": [
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "488b514507d5432da0d5b1c389f174cc",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "Downloading:   0%|          | 0.00/747 [00:00<?, ?B/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "9b39688242ea451082925eebb0ad9017",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "Downloading:   0%|          | 0.00/499M [00:00<?, ?B/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "dad1bbe9c9af4a59ba8829fbfba58515",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "Downloading:   0%|          | 0.00/899k [00:00<?, ?B/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "95e200d3e7f74591ab589cfa1d1294c3",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "Downloading:   0%|          | 0.00/456k [00:00<?, ?B/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "895cfde25be34862a6e5bcb13b218e03",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "Downloading:   0%|          | 0.00/150 [00:00<?, ?B/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "from transformers import (\n",
        "    pipeline,\n",
        "    AutoTokenizer,\n",
        "    AutoModelForSequenceClassification\n",
        "    )\n",
        "\n",
        "model_id = \"cardiffnlp/twitter-roberta-base-sentiment\"\n",
        "\n",
        "# load the model from huggingface\n",
        "model = AutoModelForSequenceClassification.from_pretrained(\n",
        "    model_id,\n",
        "    num_labels=3\n",
        ")\n",
        "\n",
        "# load the tokenizer from huggingface\n",
        "tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
        "\n",
        "# load the tokenizer and model into a sentiment analysis pipeline\n",
        "nlp = pipeline(\n",
        "    \"sentiment-analysis\",\n",
        "    model=model,\n",
        "    tokenizer=tokenizer,\n",
        "    device=device\n",
        "    )"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "cq7YEry6_IP7"
      },
      "source": [
        "The sentiment analysis model returns `LABEL_0` for negative, `LABEL_1` for neutral and `LABEL_2` for positive labels. We can add them to a dictionary to easily access them when showing the results."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "FO46eyZruYr3"
      },
      "outputs": [],
      "source": [
        "labels = {\n",
        "    \"LABEL_0\": \"negative\",\n",
        "    \"LABEL_1\": \"neutral\",\n",
        "    \"LABEL_2\": \"positive\"\n",
        "}"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 53
        },
        "id": "DH4D2kUsno6C",
        "outputId": "8d53f612-b8dd-426b-e126-d4cfa70fb451"
      },
      "outputs": [
        {
          "data": {
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            },
            "text/plain": [
              "' Room was small for a superior room and poorly lit especially as it was an inside room and overlooked the inside wall of the hotel No view therefore needed better lighting within Restaurant tables were not well laid and had to go searching for cutlery at breakfast '"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# view review number 241\n",
        "test_review = df[\"review\"][241]\n",
        "test_review"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "piRpGUiHjmBt",
        "outputId": "70f6c461-b75f-4fa4-ed21-94ec7bb1bffc"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[{'label': 'LABEL_0', 'score': 0.7736575603485107}]"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# get the sentiment label and score for review number 241\n",
        "nlp(test_review)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "cb5Ln9SHS3cu"
      },
      "source": [
        "Our pipeline is working as expected and accurately predicts the correct label for the review."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "vLK8AklElh_H"
      },
      "source": [
        "# Initialize Retriever"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "OaruW2fdTJFD"
      },
      "source": [
        "A retriever model is used to embed passages and queries, and it creates embeddings such that queries and passages with similar meanings are close in the vector space. We will use a sentence-transformer model as our retriever. The model can be loaded as follows:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6fdGP3a7HhWe"
      },
      "outputs": [],
      "source": [
        "from sentence_transformers import SentenceTransformer\n",
        "\n",
        "# load the model from huggingface\n",
        "retriever = SentenceTransformer(\n",
        "    'sentence-transformers/all-MiniLM-L6-v2',\n",
        "    device=device\n",
        ")\n",
        "retriever"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "kAQouih7Kc9X"
      },
      "source": [
        "# Initialize Pinecone Index"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "pI9ENCKlTq6m"
      },
      "source": [
        "Now we need to initialize our Pinecone index. The Pinecone index stores vector representations of our passages which we can retrieve using another vector (the query vector). We first need to initialize our connection to Pinecone. For this, we need a free [API key](https://app.pinecone.io/), we initialize the connection like so:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "gxfkKt4oX4PP"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "from pinecone import Pinecone\n",
        "\n",
        "# initialize connection to pinecone (get API key at app.pinecone.io)\n",
        "api_key = os.environ.get('PINECONE_API_KEY') or 'PINECONE_API_KEY'\n",
        "\n",
        "# configure client\n",
        "pc = Pinecone(api_key=api_key)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Now we setup our index specification, this allows us to define the cloud provider and region where we want to deploy our index. You can find a list of all [available providers and regions here](https://docs.pinecone.io/docs/projects)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from pinecone import ServerlessSpec\n",
        "\n",
        "cloud = os.environ.get('PINECONE_CLOUD') or 'aws'\n",
        "region = os.environ.get('PINECONE_REGION') or 'us-east-1'\n",
        "\n",
        "spec = ServerlessSpec(cloud=cloud, region=region)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "bWXiQV0qUqv3"
      },
      "source": [
        "Now we can create our vector index. We will name it `sentiment-mining` (feel free to choose any name you prefer). We specify the metric type as `cosine` and dimension as `384` as these are the vector space and dimensionality of the vectors generated by the retriever model."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "index_name = \"sentiment-mining\""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import time\n",
        "\n",
        "# check if index already exists (it shouldn't if this is first time)\n",
        "if index_name not in pc.list_indexes().names():\n",
        "    # if does not exist, create index\n",
        "    pc.create_index(\n",
        "        index_name,\n",
        "        dimension=384,\n",
        "        metric='cosine',\n",
        "        spec=spec\n",
        "    )\n",
        "    # wait for index to be initialized\n",
        "    while not pc.describe_index(index_name).status['ready']:\n",
        "        time.sleep(1)\n",
        "\n",
        "# connect to index\n",
        "index = pc.Index(index_name)\n",
        "# view index stats\n",
        "index.describe_index_stats()"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "X0zu4ebVYvVi"
      },
      "source": [
        "# Generate Embeddings and Upsert"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "vd6E9SEt4pM5"
      },
      "source": [
        "We generate embeddings for all the reviews in the dataset. Alongside the embeddings, we also include the sentiment label and score in the Pinecone index as metadata. Later we will use this data to understand customer opinions.\n",
        "\n",
        "Let's first write a helper function to generate sentiment labels and scores for a batch of reviews."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "0Vk1FW45LkCa"
      },
      "outputs": [],
      "source": [
        "def get_sentiment(reviews):\n",
        "    # pass the reviews through sentiment analysis pipeline\n",
        "    sentiments = nlp(reviews)\n",
        "    # extract only the label and score from the result\n",
        "    l = [labels[x[\"label\"]] for x in sentiments]\n",
        "    s = [x[\"score\"] for x in sentiments]\n",
        "    return l, s"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "xgiwvCveKXGA",
        "outputId": "60ff2bd8-c79f-45c5-a1b4-74a122107f58"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "(['negative', 'neutral', 'positive'],\n",
              " [0.906525194644928, 0.7716173529624939, 0.8975034952163696])"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# get sentiment labels for few reviews\n",
        "get_sentiment(df[\"review\"][:3].tolist())"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "ALPJvLoovaHW"
      },
      "source": [
        "We need to convert the review dates to timestamps to filter query results for a given period. This is helpful if you want to understand customer sentiment over a specific period. Let's write another helper function to convert dates to timestamps."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "q4h1OlbAFIU1"
      },
      "outputs": [],
      "source": [
        "import dateutil.parser\n",
        "\n",
        "# convert date to timestamp\n",
        "def get_timestamp(dates):\n",
        "    timestamps = [dateutil.parser.parse(d).timestamp() for d in dates]\n",
        "    return timestamps"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "-n0Xf5XtFk1B",
        "outputId": "1c66688c-fdb9-4686-c8e6-17cbb9e5ccd7"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "1501718400.0"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "get_timestamp([df[\"review_date\"][0]])[0]"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "otEH9n3hmatq"
      },
      "source": [
        "Now we create the embeddings. We do this in batches of `64` to avoid overwhelming machine resources or API request limits."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "MZ6JP50wSm9o"
      },
      "outputs": [],
      "source": [
        "from tqdm.auto import tqdm\n",
        "\n",
        "# we will use batches of 64\n",
        "batch_size = 64\n",
        "\n",
        "for i in tqdm(range(0, len(df), batch_size)):\n",
        "    # find end of batch\n",
        "    i_end = min(i+batch_size, len(df))\n",
        "    # extract batch\n",
        "    batch = df.iloc[i:i_end]\n",
        "    # generate embeddings for batch\n",
        "    emb = retriever.encode(batch[\"review\"].tolist()).tolist()\n",
        "    # convert review_date to timestamp to enable period filters\n",
        "    timestamp = get_timestamp(batch[\"review_date\"].tolist())\n",
        "    batch[\"timestamp\"] = timestamp\n",
        "    # get sentiment label and score for reviews in the batch\n",
        "    label, score = get_sentiment(batch[\"review\"].tolist())\n",
        "    batch[\"label\"] = label\n",
        "    batch[\"score\"] = score\n",
        "    # get metadata\n",
        "    meta = batch.to_dict(orient=\"records\")\n",
        "    # create unique IDs\n",
        "    ids = [f\"{idx}\" for idx in range(i, i_end)]\n",
        "    # add all to upsert list\n",
        "    to_upsert = list(zip(ids, emb, meta))\n",
        "    # upsert/insert these records to pinecone\n",
        "    _ = index.upsert(vectors=to_upsert)\n",
        " \n",
        "# check that we have all vectors in index\n",
        "index.describe_index_stats()"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "mMmWKq6VP9v2"
      },
      "source": [
        "We have successfully indexed all customer reviews and relevant metadata. We can move on to opinion mining."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "Zu-vflsWQfCQ"
      },
      "source": [
        "# Opinion Mining"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "pewxx6QkC8bC"
      },
      "source": [
        "Now that we have all the customer reviews indexed, we will search for a few areas that customers usually consider when staying at a hotel and analyze the general opinion of the customers. Pinecone vector database makes it very flexible to do this as we can easily search for any topic and get customer reviews relevant to the search query along with sentiment labels as metadata."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "jaqvfyogKbFB"
      },
      "source": [
        "We will start with a general question about the room sizes of hotels in London and return the top 500 reviews to analyze the overall customer sentiment."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "sPMquYdULWT5"
      },
      "outputs": [],
      "source": [
        "query = \"are the customers satisfied with the room sizes in London hotels?\"\n",
        "# generate dense vector embeddings for the query\n",
        "xq = retriever.encode(query).tolist()\n",
        "# query pinecone\n",
        "result = index.query(vector=xq, top_k=500, include_metadata=True)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "2te1urgsLZGO"
      },
      "source": [
        "Let's take a look at a few reviews from the search results."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "HtZFRS-HJZVt",
        "outputId": "baf5ae0b-6ba8-418c-8554-08b25ac756ca"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[{'id': '57268',\n",
              "  'metadata': {'hotel_name': 'Millennium Gloucester Hotel London',\n",
              "               'label': 'neutral',\n",
              "               'review': ' The size of the room compared to other london hotels '\n",
              "                         'And the location and friednly staff ',\n",
              "               'review_date': datetime.date(2015, 10, 9),\n",
              "               'score': 0.7984868884086609,\n",
              "               'timestamp': 1444348800.0},\n",
              "  'score': 0.819122493,\n",
              "  'sparseValues': {},\n",
              "  'values': []}, {'id': '36931',\n",
              "  'metadata': {'hotel_name': 'DoubleTree by Hilton London Docklands Riverside',\n",
              "               'label': 'positive',\n",
              "               'review': ' Rooms great but on the small size but typical for a '\n",
              "                         'London hotel',\n",
              "               'review_date': datetime.date(2015, 11, 8),\n",
              "               'score': 0.8672299981117249,\n",
              "               'timestamp': 1446940800.0},\n",
              "  'score': 0.816708684,\n",
              "  'sparseValues': {},\n",
              "  'values': []}]"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "result[\"matches\"][:2]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "P_Zk2wZ6LqAj",
        "outputId": "af9fc35c-e7f3-4277-d140-0257d594a82b"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[{'id': '60964',\n",
              "  'metadata': {'hotel_name': 'St James Court A Taj Hotel London',\n",
              "               'label': 'positive',\n",
              "               'review': ' The location is perfect and I got a late checkout as '\n",
              "                         'I requested The layout of one of the rooms made it '\n",
              "                         'feel like smaller in comparison with the others but '\n",
              "                         'they were very helpful and changed it the next '\n",
              "                         'morning Perfect hotel from a frequent traveller to '\n",
              "                         'london this hotel will be my first choice from now on',\n",
              "               'review_date': datetime.date(2016, 3, 6),\n",
              "               'score': 0.9831811785697937,\n",
              "               'timestamp': 1457222400.0},\n",
              "  'score': 0.643939376,\n",
              "  'sparseValues': {},\n",
              "  'values': []}, {'id': '46122',\n",
              "  'metadata': {'hotel_name': 'Park Grand London Kensington',\n",
              "               'label': 'positive',\n",
              "               'review': ' Bedroom was very comfortable and a great size for '\n",
              "                         'London as many rooms are rather small Had a super '\n",
              "                         'king bed which was fabulous Breakfast was very good '\n",
              "                         'and the staff both on reception and serving breakfast '\n",
              "                         'were on the whole very pleasant',\n",
              "               'review_date': datetime.date(2015, 11, 10),\n",
              "               'score': 0.985270082950592,\n",
              "               'timestamp': 1447113600.0},\n",
              "  'score': 0.643873811,\n",
              "  'sparseValues': {},\n",
              "  'values': []}]"
            ]
          },
          "execution_count": 18,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "result[\"matches\"][-2:]"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "m-ohU6DTM8hl"
      },
      "source": [
        "We have reviews relevant to room sizes from top to bottom of the search results. Now let's see the overall perception of the customers on London hotel room sizes. First, we need to extract the sentiment labels from the query results and count them. We will write a function to do this."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "GRMNxdABSjlP"
      },
      "outputs": [],
      "source": [
        "def count_sentiment(result):\n",
        "    # store count of sentiment labels\n",
        "    sentiments = {\n",
        "        \"negative\": 0,\n",
        "        \"neutral\": 0,\n",
        "        \"positive\": 0,\n",
        "    }\n",
        "    # iterate through search results\n",
        "    for r in result[\"matches\"]:\n",
        "        # extract the sentiment label and increase its count\n",
        "        sentiments[r[\"metadata\"][\"label\"]] += 1\n",
        "    return sentiments"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "B46na2RaECV_",
        "outputId": "e25125ae-6b18-4f87-be63-3de75023eb40"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'negative': 54, 'neutral': 161, 'positive': 285}"
            ]
          },
          "execution_count": 20,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "sentiment = count_sentiment(result)\n",
        "sentiment"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "ml9C7bdCNm9P"
      },
      "source": [
        "Let's plot the result for a better view."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 282
        },
        "id": "AZEBuoOREiUZ",
        "outputId": "dcbdd96a-487a-42da-9501-25a5af70f52a"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<matplotlib.axes._subplots.AxesSubplot at 0x7f4a962d9890>"
            ]
          },
          "execution_count": 21,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "image/png": "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",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "needs_background": "light"
          },
          "output_type": "display_data"
        }
      ],
      "source": [
        "import seaborn as sns\n",
        "\n",
        "# plot a barchart using seaborn\n",
        "sns.barplot(x=list(sentiment.keys()), y = list(sentiment.values()))"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "JVzKE1-FNxRr"
      },
      "source": [
        "The customers are generally satisfied with the room sizes, although many are still neutral and negative."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "c9CGZPeVJ8g_"
      },
      "source": [
        "We can be even more specific when searching for reviews with the help of Pinecone's metadata filtering. For instance, we can specify a period in our query to ensure that search results only contain customer reviews for that period. This is helpful if you want to understand the customer's opinion during a specific period.\n",
        "\n",
        "Let's do this for the same query as before. We will filter reviews from 25th December to 31st December 2015. Previously we added the `review_date` field as a timestamp to the metadata during indexing. We can convert the start and end date of the period to timestamp using the `get_timestamp` function and use a `$gte` (greater than or equal to) and a `$lte` (less than or equal to) filter to get reviews from only the selected period."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "BsjQAwIPMwch"
      },
      "outputs": [],
      "source": [
        "# generate timestamps for start and end time of the period\n",
        "start_time = get_timestamp([\"2015-12-25\"])[0]\n",
        "end_time = get_timestamp([\"2015-12-31\"])[0]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 282
        },
        "id": "KXvuWmcLKyH4",
        "outputId": "9bcc7e50-06d0-4229-c399-c3acd5950a9a"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<matplotlib.axes._subplots.AxesSubplot at 0x7f4a95c2ee90>"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "image/png": "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",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "needs_background": "light"
          },
          "output_type": "display_data"
        }
      ],
      "source": [
        "query = \"are the customers satisified with the room sizes of hotels in London?\"\n",
        "# generate query embeddings\n",
        "xq = retriever.encode(query).tolist()\n",
        "# query pinecone with query embeddings and the period filter\n",
        "result = index.query(\n",
        "    vector=xq,\n",
        "    top_k=500,\n",
        "    include_metadata=True,\n",
        "    filter={\"timestamp\": {\"$gte\": start_time, \"$lte\":end_time}})\n",
        "# get an overall count of customer sentiment\n",
        "sentiment = count_sentiment(result)\n",
        "# plot a barchart using seaborn\n",
        "sns.barplot(x=list(sentiment.keys()), y = list(sentiment.values()))"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "wMhej5iWeue0"
      },
      "source": [
        "We have a slightly different result now. Almost the same number of customers had either a neutral or negative view of the room size during the selected period."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "S0S-fMCuaC3e"
      },
      "outputs": [],
      "source": [
        "hotels =[\n",
        "    \"Strand Palace Hotel\",\n",
        "    \"Britannia International Hotel Canary Wharf\",\n",
        "    \"Grand Royale London Hyde Park\",\n",
        "    \"Intercontinental London The O2\",\n",
        "]"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "rSKy4xGsW0aD"
      },
      "source": [
        "We will look into five main areas:\n",
        "  1. Room Size\n",
        "  2. Cleanliness\n",
        "  3. Staff\n",
        "  4. Food\n",
        "  5. AC\n",
        "\n",
        "We have a query for each of these areas below."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "LM1T5fk4YsJx"
      },
      "outputs": [],
      "source": [
        "queries = {\n",
        "    \"Room Size\": \"are customers happy with the room sizes?\",\n",
        "    \"Cleanliness\": \"are customers satisfied with the cleanliness of the rooms?\",\n",
        "    \"Staff\": \"did the customers like how they were treated by the staff?\",\n",
        "    \"Food\": \"did the customers enjoy the food?\",\n",
        "    \"AC\": \"customer opinion on the AC\"\n",
        "}"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "SXE5OphsQICa"
      },
      "source": [
        "We need to iterate through all the hotels and run these queries for each hotel. This would give us customer reviews relevant to the selected hotel areas. After that, we count the sentiment labels and plot results for each hotel."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "b97hFJXaaxRy"
      },
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "import pandas as pd\n",
        "\n",
        "hotel_sentiments = []\n",
        "\n",
        "# iterate through the hotels\n",
        "for hotel in hotels:\n",
        "    result = []\n",
        "    # iterate through the keys and values in the queries dict\n",
        "    for area, query in queries.items():\n",
        "        # generate query embeddings\n",
        "        xq = retriever.encode(query).tolist()\n",
        "        # query pinecone with query embeddings and the hotel filter\n",
        "        xc = index.query(vector=xq, top_k=500, include_metadata=True, filter={\"hotel_name\": hotel})\n",
        "        # get an overall count of customer sentiment\n",
        "        sentiment = count_sentiment(xc)\n",
        "        # sort the sentiment to show area and each value side by side\n",
        "        for k, v in sentiment.items():\n",
        "            data = {\n",
        "                \"area\": area,\n",
        "                \"label\": k,\n",
        "                \"value\": v \n",
        "            }\n",
        "            # add the data to result list\n",
        "            result.append(data)\n",
        "    # convert the      \n",
        "    hotel_sentiments.append({\"hotel\": hotel, \"df\": pd.DataFrame(result)})\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "Tm7BCgWZQvT1"
      },
      "source": [
        "Let's see what our final data look like."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 520
        },
        "id": "-qZdKfWIQhfv",
        "outputId": "644bc20f-8f2c-43c6-9fec-b37fff3b50ae"
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-401ac15f-793e-4bce-8a1a-10e2b983d865\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>area</th>\n",
              "      <th>label</th>\n",
              "      <th>value</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>Room Size</td>\n",
              "      <td>negative</td>\n",
              "      <td>127</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>Room Size</td>\n",
              "      <td>neutral</td>\n",
              "      <td>187</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>Room Size</td>\n",
              "      <td>positive</td>\n",
              "      <td>186</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>Cleanliness</td>\n",
              "      <td>negative</td>\n",
              "      <td>90</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>Cleanliness</td>\n",
              "      <td>neutral</td>\n",
              "      <td>67</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>5</th>\n",
              "      <td>Cleanliness</td>\n",
              "      <td>positive</td>\n",
              "      <td>343</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>6</th>\n",
              "      <td>Staff</td>\n",
              "      <td>negative</td>\n",
              "      <td>68</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>7</th>\n",
              "      <td>Staff</td>\n",
              "      <td>neutral</td>\n",
              "      <td>36</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>8</th>\n",
              "      <td>Staff</td>\n",
              "      <td>positive</td>\n",
              "      <td>396</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>9</th>\n",
              "      <td>Food</td>\n",
              "      <td>negative</td>\n",
              "      <td>95</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>10</th>\n",
              "      <td>Food</td>\n",
              "      <td>neutral</td>\n",
              "      <td>54</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>11</th>\n",
              "      <td>Food</td>\n",
              "      <td>positive</td>\n",
              "      <td>351</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>12</th>\n",
              "      <td>AC</td>\n",
              "      <td>negative</td>\n",
              "      <td>175</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>13</th>\n",
              "      <td>AC</td>\n",
              "      <td>neutral</td>\n",
              "      <td>100</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>14</th>\n",
              "      <td>AC</td>\n",
              "      <td>positive</td>\n",
              "      <td>225</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-401ac15f-793e-4bce-8a1a-10e2b983d865')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-401ac15f-793e-4bce-8a1a-10e2b983d865 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-401ac15f-793e-4bce-8a1a-10e2b983d865');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "           area     label  value\n",
              "0     Room Size  negative    127\n",
              "1     Room Size   neutral    187\n",
              "2     Room Size  positive    186\n",
              "3   Cleanliness  negative     90\n",
              "4   Cleanliness   neutral     67\n",
              "5   Cleanliness  positive    343\n",
              "6         Staff  negative     68\n",
              "7         Staff   neutral     36\n",
              "8         Staff  positive    396\n",
              "9          Food  negative     95\n",
              "10         Food   neutral     54\n",
              "11         Food  positive    351\n",
              "12           AC  negative    175\n",
              "13           AC   neutral    100\n",
              "14           AC  positive    225"
            ]
          },
          "execution_count": 55,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "hotel_sentiments[0][\"df\"]"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "xIIBrwjwQglY"
      },
      "source": [
        "We may now plot the final data to make inference."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 302
        },
        "id": "KypU0GOsO-_i",
        "outputId": "f27ca0bb-8e10-4eab-d85d-4e508371e505"
      },
      "outputs": [
        {
          "data": {
            "image/png": "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",
            "text/plain": [
              "<Figure size 1800x324 with 4 Axes>"
            ]
          },
          "metadata": {
            "needs_background": "light"
          },
          "output_type": "display_data"
        }
      ],
      "source": [
        "# create the figure and axes to plot barchart for all hotels\n",
        "fig, axs = plt.subplots(nrows=1, ncols=4, figsize=(25, 4.5))\n",
        "plt.subplots_adjust(hspace=0.25)\n",
        "\n",
        "counter = 0\n",
        "# iterate through each hotel in the list and plot a barchart\n",
        "for d, ax in zip(hotel_sentiments, axs.ravel()):\n",
        "    # plot barchart for each hotel\n",
        "    sns.barplot(x=\"label\", y=\"value\", hue=\"area\", data=d[\"df\"], ax=ax)\n",
        "    # display the hotel names\n",
        "    ax.set_title(d[\"hotel\"])\n",
        "    # remove x labels\n",
        "    ax.set_xlabel(\"\")\n",
        "    # remove legend from all charts except for the first one\n",
        "    counter += 1\n",
        "    if counter != 1: ax.get_legend().remove()\n",
        "# display the full figure\n",
        "plt.show()"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "9hEvl0eXTUBd"
      },
      "source": [
        "The following observations can be made for the hotels based on the sentiment analysis:\n",
        "1.  **Strand Palace Hotel:** most customers were pleased with the staff, food, and cleanliness of the rooms, while a considerable number of them were not very satisfied with the room sizes and the AC.\n",
        "2.  **Britannia International Hotel Canary Wharf:** customers were quite happy with the room size, but the majority were not satisfied with the AC.\n",
        "3.  **Grand Royale London Hyde Park**: the majority of the customers were not satisfied with the room size, while a good number of them were pretty satisfied with the food, staff, AC, and cleanliness of the rooms.\n",
        "4.  **Intercontinental London The O2**: the majority of the customers were really happy with the selected five areas, making this hotel the best among the selected hotels.\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "Zmkfg0PpfSZ1"
      },
      "source": [
        "Although we have experimented with a few selected areas, you can get creative with your queries and get the sentiment around your area of interest immediately. This approach can even be applied to live data as the Pinecone index refreshes in real-time and performs vector searches across billions of documents with millisecond latency."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Delete Index\n",
        "\n",
        "Delete the index if you're finished to save resources:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "pc.delete_index(index_name)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "---"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "provenance": []
    },
    "gpuClass": "standard",
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.10.7 (main, Sep 14 2022, 22:38:23) [Clang 14.0.0 (clang-1400.0.29.102)]"
    },
    "vscode": {
      "interpreter": {
        "hash": "b0fa6594d8f4cbf19f97940f81e996739fb7646882a419484c72d19e05852a7e"
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}